home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / daemons / init / sysvinit.000 / sysvinit / sysvinit-2.64 / powerd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-02  |  4.2 KB  |  193 lines

  1. /*
  2.  * powerd    Monitor the DCD line of a serial port connected to
  3.  *        an UPS. If the power goes down, notify init.
  4.  *        If the power comes up again, notify init again.
  5.  *        As long as the power is OK, the DCD line should be
  6.  *        "HIGH". When the power fails, DCD should go "LOW".
  7.  *        Powerd keeps DTR high so that you can connect
  8.  *        DCD and DTR with a resistor of 10 Kilo Ohm and let the
  9.  *        UPS or some relais pull the DCD line to ground.
  10.  *        You also need to connect DTR and DSR together. This
  11.  *        way, powerd can check now and then if DSR is high
  12.  *        so it knows the UPS is connected!!
  13.  *
  14.  * Usage:    powerd /dev/cua4 (or any other serial device).
  15.  *
  16.  * Author:    Miquel van Smoorenburg, <miquels@drinkel.cistron.nl>.
  17.  *
  18.  * Version:    1.31,  29-Feb-1996.
  19.  *
  20.  *        This program was originally written for my employer,
  21.  *            ** Cistron Electronics **
  22.  *        who has given kind permission to release this program
  23.  *        for general puppose.
  24.  *
  25.  *        Copyright 1991-1996 Cistron Electronics.
  26.  *
  27.  *        This program is free software; you can redistribute it and/or
  28.  *        modify it under the terms of the GNU General Public License
  29.  *        as published by the Free Software Foundation; either version
  30.  *        2 of the License, or (at your option) any later version.
  31.  */
  32.  
  33. /* Use the new way of communicating with init. */
  34. #define NEWINIT
  35.  
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include <sys/ioctl.h>
  39. #include <fcntl.h>
  40. #include <errno.h>
  41. #include <stdlib.h>
  42. #include <unistd.h>
  43. #include <stdio.h>
  44. #include <signal.h>
  45. #include <syslog.h>
  46. #include <string.h>
  47. #include "paths.h"
  48. #ifdef NEWINIT
  49. #include "initreq.h"
  50. #endif
  51.  
  52. #ifndef SIGPWR
  53. #  define SIGPWR SIGUSR1
  54. #endif
  55.  
  56. #ifdef NEWINIT
  57. void alrm_handler()
  58. {
  59. }
  60. #endif
  61.  
  62. /* Tell init the power has either gone or is back. */
  63. void powerfail(ok)
  64. int ok;
  65. {
  66.   int fd;
  67. #ifdef NEWINIT
  68.   struct init_request req;
  69.  
  70.   /* Fill out the request struct. */
  71.   memset(&req, 0, sizeof(req));
  72.   req.magic = INIT_MAGIC;
  73.   req.cmd   = ok ? INIT_CMD_POWEROK : INIT_CMD_POWERFAIL;
  74.  
  75.   /* Open the fifo (with timeout) */
  76.   signal(SIGALRM, alrm_handler);
  77.   alarm(3);
  78.   if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0
  79.         && write(fd, &req, sizeof(req)) == sizeof(req)) {
  80.     close(fd);
  81.     return;
  82.   }
  83.   /* Fall through to the old method.. */
  84. #endif
  85.  
  86.   /* Create an info file for init. */
  87.   unlink(PWRSTAT);
  88.   if ((fd = open(PWRSTAT, O_CREAT|O_WRONLY, 0644)) >= 0) {
  89.     if (ok)
  90.         write(fd, "OK\n", 3);
  91.     else
  92.         write(fd, "FAIL\n", 5);
  93.     close(fd);
  94.   }
  95.   kill(1, SIGPWR);
  96. }
  97.  
  98. /* Main program. */
  99. int main(int argc, char **argv)
  100. {
  101.   int fd;
  102.   int dtr_bit = TIOCM_DTR;
  103.   int flags;
  104.   int status, oldstat = -1;
  105.   int count = 0;
  106.   int tries = 0;
  107.  
  108.   if (argc < 2) {
  109.     fprintf(stderr, "Usage: powerd <device>\n");
  110.     exit(1);
  111.   }
  112.  
  113.   /* Start syslog. */
  114.   openlog("powerd", LOG_CONS|LOG_PERROR, LOG_DAEMON);
  115.  
  116.   /* Open monitor device. */
  117.   if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {
  118.     syslog(LOG_ERR, "%s: %s", argv[1], sys_errlist[errno]);
  119.     closelog();
  120.     exit(1);
  121.   }
  122.  
  123.   /* Line is opened, so DTR is high. Force it anyway to be sure. */
  124.   ioctl(fd, TIOCMBIS, &dtr_bit);
  125.  
  126.   /* Daemonize. */
  127.   switch(fork()) {
  128.     case 0: /* Child */
  129.         closelog();
  130.         setsid();
  131.         break;
  132.     case -1: /* Error */
  133.         syslog(LOG_ERR, "can't fork.");
  134.         closelog();
  135.         exit(1);
  136.     default: /* Parent */
  137.         closelog();
  138.         exit(0);
  139.   }
  140.  
  141.   /* Restart syslog. */
  142.   openlog("powerd", LOG_CONS, LOG_DAEMON);
  143.  
  144.   /* Now sample the DCD line. */
  145.   while(1) {
  146.     /* Get the status. */
  147.     ioctl(fd, TIOCMGET, &flags);
  148.  
  149.     /* Check the connection: DSR should be high. */
  150.     tries = 0;
  151.     while((flags & TIOCM_DSR) == 0) {
  152.         /* Keep on trying, and warn every two minutes. */
  153.         if ((tries % 60) == 0)
  154.             syslog(LOG_ALERT, "UPS connection error");
  155.         sleep(2);
  156.         tries++;
  157.           ioctl(fd, TIOCMGET, &flags);
  158.     }
  159.     if (tries > 0)
  160.         syslog(LOG_ALERT, "UPS connection OK");
  161.  
  162.     /* Calculate present status. */
  163.     status = (flags & TIOCM_CAR);
  164.  
  165.     /* Did DCD drop to zero? Then the power has failed. */
  166.     if (oldstat != 0 && status == 0) {
  167.         count++;
  168.         if (count > 3)
  169.             powerfail(0);
  170.         else {
  171.             sleep(1);
  172.             continue;
  173.         }
  174.     }
  175.     /* Did DCD come up again? Then the power is back. */
  176.     if (oldstat == 0 && status > 0) {
  177.         count++;
  178.         if (count > 3)
  179.             powerfail(1);
  180.         else {
  181.             sleep(1);
  182.             continue;
  183.         }
  184.     }
  185.     /* Reset count, remember status and sleep 2 seconds. */
  186.     count = 0;
  187.     oldstat = status;
  188.     sleep(2);
  189.   }
  190.   /* Never happens */
  191.   return(0);
  192. }
  193.